/*
 * Projeto GADJE
 * 
 * Criado em: 17/02/2013
 */
package br.com.gadje.dominiopersistencia.modelo;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.OutputStreamWriter;
import java.io.Serializable;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.persistence.Table;

import org.springframework.core.io.support.PropertiesLoaderUtils;

/**
 * Classe que representa o modelo de objetos do sistema para persistência.
 * 
 * @author Anderson Santos
 *
 */
public abstract class ModeloPersistencia implements Cloneable, Serializable {
	/**
	 * Número serial devido à implementação de Serializable.
	 */
	public static final long serialVersionUID = 1L;
	
	/**
	 * Método usado para alterar o ID do objeto.
	 * 
	 * @param id
	 */
	public abstract void setId(long id);
	
	/**
	 * Método usado para obter o ID do objeto.
	 * 
	 * return
	 */
	public abstract long getId();
	
	/**
	 * Caminho do arquivo com a sequência dos ids.
	 */
	private static String caminho;
	
	/**
	 * Método usado para gerar o ID dos objetos automaticamente e incrementa o gerador de acordo com o incremento.
	 * 
	 * @param classe
	 * @param incremento
	 * @return
	 */
	private final static <Classe extends ModeloPersistencia> long gerarAutomaticamenteID(Class<Classe> classe, int incremento) {
		long id = 0;
		
		try {
			if (caminho == null) {
				Properties propriedades = PropertiesLoaderUtils.loadAllProperties("conf_persistencia.properties");
				caminho = propriedades.get("localizacao_arquivo_id").toString();
			}
			
			StringBuffer texto = new StringBuffer("");
			
			//Leitura do arquivo de sequências.
			BufferedReader arquivoLeitura = new BufferedReader(new FileReader(caminho));
			
			while (arquivoLeitura.ready()) {
				texto.append(arquivoLeitura.readLine() + "\r\n");
            }
			
			arquivoLeitura.close();
			
			Pattern pattern = Pattern.compile("\\b" + ((Table) classe.getAnnotation(Table.class)).name() + "=\\d+");
			Matcher matcher = pattern.matcher(texto.toString());
		    
			String novoTexto = "";
			
		    if (matcher.find()) {
		    	int um = 1;
		    	id = Long.parseLong(matcher.group().split("=")[um]);
		    	novoTexto = texto.toString().replaceFirst(matcher.group(), matcher.group().replaceFirst("\\d+", String.valueOf(id + incremento)));
		    }
		     
			//Escrita no arquivo de ids.
			BufferedWriter arquivoEscrita = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(caminho)));
			arquivoEscrita.write(novoTexto.toString());
			arquivoEscrita.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		return id;
	}
	
	/**
	 * Método usado para gerar o ID dos objetos automaticamente.
	 * 
	 * @param classe
	 * @return
	 */
	public final static <Classe extends ModeloPersistencia> long gerarAutomaticamenteID(Class<Classe> classe) {
		int incremento = 1;
		return gerarAutomaticamenteID(classe, incremento);
	}
	
	/**
	 * Método usado para reservar ids usados nas inserções em massa.
	 * 
	 * @param classe
	 * @param quantidade
	 * @return
	 */
	public final static <Classe extends ModeloPersistencia> long reservarID(Class<Classe> classe, int quantidade) {
		return gerarAutomaticamenteID(classe, quantidade);
	}
	
	/**
	 * Método usado para obter o código hash de objetos do tipo ModeloPersistencia.
	 * 
	 * @return
	 */
	public int hashCode() {
		return (int)((getId() >> 32) ^ getId());
	}
	
	/**
	 * Método usado para comparar objetos do tipo ModeloPersistencia.
	 * 
	 * @return
	 */
	public boolean equals(Object objeto) {
		boolean resultado = false;
		
		if (this == objeto) {
			resultado = true;
		} else if (objeto == null) {
			resultado = false;
		} else if (getClass() != objeto.getClass()) {
			resultado = false;
		} else {
			resultado = (this.getId() == ((ModeloPersistencia) objeto).getId());
		}
		
		return resultado;
	}
}
